//
//  POPGestureRecognizerManager.swift
//  ScreenPoP
//
//  Created by 万孟超 on 2023/3/17.
//  Copyright © 2023 wanmengchao. All rights reserved.
//

import UIKit

public class POPGestureRecognizerManager: NSObject {
    
    private let screenWidth = UIScreen.main.bounds.width
    
    private let screenHeight = UIScreen.main.bounds.height
    
    private var shapeLayer: CAShapeLayer?
    
    private var homeLeftPoint = CGPoint.zero
    
    private var farPoint = CGPoint.zero
    
    private var isPopToRootController: Bool = false
    
    /// 获取当前Window
    private var currentWindow : UIWindow? {
        if #available(iOS 14.0, *) {
            if let window = UIApplication.shared.connectedScenes.map({$0 as? UIWindowScene}).compactMap({$0}).first?.windows.first {
                return window
            }else if let window = UIApplication.shared.delegate?.window {
                return window
            }else{
                return nil
            }
        } else if #available(iOS 13.0, *) {
            if let window = UIApplication.shared.connectedScenes.filter({$0.activationState == .foregroundActive}).map({$0 as? UIWindowScene}).compactMap({$0}).first?.windows.filter({$0.isKeyWindow}).first{
                return window
            }else if let window = UIApplication.shared.delegate?.window {
                return window
            }else{
                return nil
            }
        }else{
            if let window = UIApplication.shared.delegate?.window {
                return window
            }else{
                return nil
            }
        }
    }
    
    @objc public var config = POPGestureRecognizeConfiger()
    
    @objc public var delegate: POPGestureRecognizerManagerProtocol?
    
    @objc public static let shared = POPGestureRecognizerManager()
    
    @objc public func registerManger(configer: POPGestureRecognizeConfiger? = nil,
                        completeBlock: ((Bool, String) -> ())? = nil) {
        if let configer = configer {
            config = configer
        }
        addScreenEdgePanGestureToWindow()
        completeBlock?(true, "当前controller为导航控制器的根控制器时，拖动无效果")
#if DEBUG
        print("==========Manager注册信息==========");
        print("NavigationController:%@",self.config.navigationController as Any);
        print("拖动时的背景颜色R:%g G:%g B:%g ",self.config.backGroundColor.cgColor.components![0] * 255,self.config.backGroundColor.cgColor.components![1] * 255,self.config.backGroundColor.cgColor.components![2] * 255);
        print("背景颜色Alpha值:%g",self.config.backGroundAlpha);
        print("拖动时展示的图片:%@",self.config.returnImage as Any);
        if ((self.config.imageColor) != nil) {
            print("拖动时图片的颜色:R:%g G:%g B:%g ",self.config.imageColor!.cgColor.components![0] * 255,self.config.imageColor!.cgColor.components![1] * 255,self.config.imageColor!.cgColor.components![2] * 255);
    }else{
        print("不改变拖动时图片的颜色");
    }
        print("是否跟随手势位置移动:%@",self.config.isFollowGesturePosition ? "是" : "否");
        print("是否可以返回首页:%@",self.config.isCanPopToRootViewController ? "是" : "否");
        print("返回首页拖动时展示的图片:%@",self.config.returnImage as Any);
        print("返回首页拖动触发时间:%g",self.config.returnHomeTime);
        print("是否展示返回动画:%@",self.config.isShowPopAnimated ? "是" : "否");
#endif
    }
    
    func addScreenEdgePanGestureToWindow() {
        let gesture = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(screenEdgePanGestureExcuteEvent(gesture:)))
        gesture.edges = .right
        currentWindow?.addGestureRecognizer(gesture)
    }
    
    @objc func screenEdgePanGestureExcuteEvent(gesture: UIScreenEdgePanGestureRecognizer) {
        if config.navigationController?.viewControllers.count == 1 {
            return
        }
        let changePoint = gesture.location(in: currentWindow)
        if gesture.state == .began {
            farPoint = changePoint
        }
        if gesture.state == .changed {
            if changePoint.x < farPoint.x {
                farPoint = changePoint
            }
            if config.isCanPopToRootViewController {
                if homeLeftPoint.x > changePoint.x + 3 || homeLeftPoint.x < changePoint.x - 3 {
                    createLayer(progressPoint: changePoint)
                    isPopToRootController = false
                    NSObject.cancelPreviousPerformRequests(withTarget: self)
                    perform(#selector(changeReturnType(pointX:)), with: changePoint.x, afterDelay: TimeInterval(config.returnHomeTime))
                }
            }else{
                createLayer(progressPoint: changePoint)
            }
        }
        if gesture.state == .ended {
            let anim = CABasicAnimation()
            anim.keyPath = "position"
            anim.duration = 0.5
            if let shapeLayer = shapeLayer {
                anim.fromValue = NSValue(cgPoint: shapeLayer.position)
                anim.toValue = NSValue(cgPoint: CGPoint(x: shapeLayer.position.x + 55, y: shapeLayer.position.y))
                anim.fillMode = .forwards
                anim.isRemovedOnCompletion = false
                shapeLayer.add(anim, forKey: nil)
            }
            if changePoint.x < farPoint.x + 20 {
                guard let navigationController = config.navigationController else { return }
                if !isPopToRootController {
                    if let delegate = delegate {
                        var lastController : UIViewController? = nil
                        let controllerCount = navigationController.viewControllers.count
                        if controllerCount >= 2 {
                            lastController = navigationController.viewControllers[controllerCount - 2]
                        }
                        if let pop = delegate.gestureRecognizerPopLastController?(lastController: lastController, currentController: navigationController.topViewController!) {
                            if pop {
                                navigationController.popViewController(animated: config.isShowPopAnimated)
                            }
                        }
                    }else{
                        navigationController.popViewController(animated: config.isShowPopAnimated)
                    }
                }else{
                    if let delegate = delegate {
                        if let canBackHome = delegate.gestureRecognizerBackHomeController?(currentController: config.navigationController?.viewControllers.first) {
                            if canBackHome {
                                config.navigationController?.popToRootViewController(animated: config.isShowPopAnimated)
                            }
                        }
                    }else{
                        config.navigationController?.popToRootViewController(animated: config.isShowPopAnimated)
                    }
                }
            }
        }
    }
    
    /**
     创建背景layer
     
     @param progressPoint 滑动点
     */
    func createLayer(progressPoint: CGPoint) {
        var tempPoint = CGPoint.zero
        if (progressPoint.x < screenWidth - 40) {
            tempPoint = CGPointMake(screenWidth - 40, progressPoint.y)
        }else{
            tempPoint = progressPoint
        }
        if (config.isFollowGesturePosition) {
            if (progressPoint.y <= 100) {
                tempPoint = CGPointMake(tempPoint.x, 100)
            }else if (progressPoint.y >= screenHeight - 100) {
                tempPoint = CGPointMake(tempPoint.x, screenHeight - 100)
            }
        }else{
            tempPoint = CGPointMake(tempPoint.x, screenHeight / 2)
        }
        shapeLayer?.removeFromSuperlayer()
        shapeLayer = CAShapeLayer();
        shapeLayer?.backgroundColor = UIColor.clear.cgColor
        shapeLayer?.frame = CGRectMake(0, 0, screenWidth, screenHeight)
        shapeLayer?.lineJoin = .round
        shapeLayer?.lineCap = .round
        let subLayer = CALayer()
        subLayer.backgroundColor = UIColor.clear.cgColor
        let image = config.returnImage
        if var image = image {
            if let color = config.homeImageColor {
                image = image.imageColor(color)
            }
            subLayer.contents = image.cgImage
        }
        
        subLayer.frame = CGRectMake(tempPoint.x + 10, tempPoint.y - 15, 30, 30);
        let path = UIBezierPath()
        path.lineWidth = 1
        path.usesEvenOddFillRule = true
        path.move(to: CGPointMake(screenWidth, tempPoint.y - 100))
        path.addQuadCurve(to: CGPointMake(tempPoint.x + 10 * (screenWidth - tempPoint.x) / 40, tempPoint.y - 20), controlPoint: CGPointMake(screenWidth, tempPoint.y - 70))
        path.addQuadCurve(to: CGPointMake(tempPoint.x + 10 * (screenWidth - tempPoint.x) / 40, tempPoint.y + 20), controlPoint: CGPointMake(tempPoint.x - 0 * (screenWidth - tempPoint.x) / 40, tempPoint.y))
        path.addQuadCurve(to: CGPointMake(screenWidth, tempPoint.y + 100), controlPoint: CGPointMake(screenWidth, tempPoint.y + 70))
        path.close()
        shapeLayer?.fillColor = config.backGroundColor.withAlphaComponent(CGFloat(config.backGroundAlpha)).cgColor
        shapeLayer?.path = path.cgPath
        shapeLayer?.addSublayer(subLayer)
        currentWindow?.layer.addSublayer(shapeLayer!)
    }
    
    /**
     改变返回执行类型以及图标
     */
    @objc func changeReturnType(pointX: Float) {
        homeLeftPoint = CGPointMake(CGFloat(pointX), 0)
        isPopToRootController = true
        if let layer = shapeLayer?.sublayers?.first {
            if var image = config.returnHomeImage {
                if let color = config.homeImageColor {
                    image = image.imageColor(color)
                }
                layer.contents = image.cgImage
            }
        }
    }
}
